import { Context } from 'koa';
import { query, queryOne } from '../database/mysql';
import { Log } from '../database/models';
import { success, error } from '../utils/response';
import { ResponseCode } from '../config/responseCode';

/**
 * 查询日志列表（仅管理员，支持分页和条件查询）
 */
export async function getLogList(ctx: Context): Promise<void> {
  const {
    page = 1,
    pageSize = 20,
    type,
    level,
    userId,
    requestId,
    startTime,
    endTime,
    keyword,
  } = ctx.request.body as {
    page?: number;
    pageSize?: number;
    type?: string;
    level?: string;
    userId?: string;
    requestId?: string;
    startTime?: string;
    endTime?: string;
    keyword?: string;
  };

  // 限制每页最大数量，防止查询过大数据
  const maxPageSize = 100;
  const limitPageSize = Math.min(pageSize, maxPageSize);
  const offset = (page - 1) * limitPageSize;

  // 构建查询条件
  let sql = 'SELECT * FROM logs WHERE 1=1';
  const params: any[] = [];

  if (type) {
    sql += ' AND type = ?';
    params.push(type);
  }

  if (level) {
    sql += ' AND level = ?';
    params.push(level);
  }

  if (userId) {
    sql += ' AND user_id = ?';
    params.push(userId);
  }

  if (requestId) {
    sql += ' AND request_id = ?';
    params.push(requestId);
  }

  if (startTime) {
    sql += ' AND created_at >= ?';
    params.push(startTime);
  }

  if (endTime) {
    sql += ' AND created_at <= ?';
    params.push(endTime);
  }

  if (keyword) {
    sql += ' AND (message LIKE ? OR url LIKE ?)';
    const keywordPattern = `%${keyword}%`;
    params.push(keywordPattern, keywordPattern);
  }

  // 按时间倒序排列，使用索引优化
  sql += ' ORDER BY created_at DESC LIMIT ? OFFSET ?';
  params.push(limitPageSize, offset);

  // 执行查询
  const logs = await query<Log>(sql, params);

  // 查询总数（优化：只在需要时查询总数）
  let total = 0;
  if (page === 1 || logs.length === limitPageSize) {
    let countSql = 'SELECT COUNT(*) as count FROM logs WHERE 1=1';
    const countParams: any[] = [];

    if (type) {
      countSql += ' AND type = ?';
      countParams.push(type);
    }

    if (level) {
      countSql += ' AND level = ?';
      countParams.push(level);
    }

    if (userId) {
      countSql += ' AND user_id = ?';
      countParams.push(userId);
    }

    if (requestId) {
      countSql += ' AND request_id = ?';
      countParams.push(requestId);
    }

    if (startTime) {
      countSql += ' AND created_at >= ?';
      countParams.push(startTime);
    }

    if (endTime) {
      countSql += ' AND created_at <= ?';
      countParams.push(endTime);
    }

    if (keyword) {
      countSql += ' AND (message LIKE ? OR url LIKE ?)';
      const keywordPattern = `%${keyword}%`;
      countParams.push(keywordPattern, keywordPattern);
    }

    const totalResult = await queryOne<{ count: number }>(countSql, countParams);
    total = totalResult?.count || 0;
  } else {
    // 如果不是第一页且返回的数据少于 pageSize，说明是最后一页
    total = (page - 1) * limitPageSize + logs.length;
  }

  // 解析 data 字段（JSON 字符串）
  const logList = logs.map(log => {
    let parsedData = null;
    if (log.data) {
      try {
        parsedData = JSON.parse(log.data);
      } catch (e) {
        // 如果解析失败，保持原样
        parsedData = log.data;
      }
    }
    return {
      ...log,
      data: parsedData,
    };
  });

  success(ctx, {
    list: logList,
    total,
    page,
    pageSize: limitPageSize,
  });
}

/**
 * 查询日志详情
 */
export async function getLogDetail(ctx: Context): Promise<void> {
  const { id } = ctx.request.body as { id?: string };

  if (!id) {
    error(ctx, ResponseCode.BAD_REQUEST, '日志ID不能为空');
    return;
  }

  const log = await queryOne<Log>('SELECT * FROM logs WHERE id = ?', [id]);
  if (!log) {
    error(ctx, ResponseCode.NOT_FOUND, '日志不存在');
    return;
  }

  // 解析 data 字段
  let parsedData = null;
  if (log.data) {
    try {
      parsedData = JSON.parse(log.data);
    } catch (e) {
      parsedData = log.data;
    }
  }

  success(ctx, {
    ...log,
    data: parsedData,
  });
}

/**
 * 删除旧日志（仅管理员）
 * 删除指定天数之前的日志
 */
export async function deleteOldLogs(ctx: Context): Promise<void> {
  const { days = 30 } = ctx.request.body as { days?: number };

  if (days < 1) {
    error(ctx, ResponseCode.BAD_REQUEST, '保留天数必须大于0');
    return;
  }

  // 计算删除的截止时间
  const cutoffDate = new Date();
  cutoffDate.setDate(cutoffDate.getDate() - days);
  const cutoffDateStr = cutoffDate.toISOString().slice(0, 19).replace('T', ' ');

  // 先查询要删除的数量
  const countResult = await queryOne<{ count: number }>(
    'SELECT COUNT(*) as count FROM logs WHERE created_at < ?',
    [cutoffDateStr]
  );
  const deleteCount = countResult?.count || 0;

  if (deleteCount === 0) {
    success(ctx, {
      message: '没有需要删除的旧日志',
      deletedCount: 0,
    });
    return;
  }

  // 执行删除
  await query('DELETE FROM logs WHERE created_at < ?', [cutoffDateStr]);

  success(ctx, {
    message: `成功删除 ${deleteCount} 条旧日志`,
    deletedCount: deleteCount,
    cutoffDate: cutoffDateStr,
  });
}

/**
 * 获取日志统计信息
 * 返回：日志总数、各个类型日志数、各个级别日志数、今天日志数
 */
export async function getLogStats(ctx: Context): Promise<void> {
  // 计算今天的开始时间（使用本地时间，避免时区问题）
  const today = new Date();
  today.setHours(0, 0, 0, 0);
  // 格式化为 MySQL 日期时间格式：YYYY-MM-DD HH:mm:ss
  const todayYear = today.getFullYear();
  const todayMonth = String(today.getMonth() + 1).padStart(2, '0');
  const todayDay = String(today.getDate()).padStart(2, '0');
  const todayStr = `${todayYear}-${todayMonth}-${todayDay} 00:00:00`;

  // 日志总数（所有日志）
  const totalResult = await queryOne<{ count: string | number | bigint }>(
    'SELECT COUNT(*) as count FROM logs'
  );
  const total = totalResult ? Number(totalResult.count) || 0 : 0;

  // 按类型统计（所有日志）
  const typeStatsRaw = await query<{ type: string; count: string | number | bigint }>(
    `SELECT type, COUNT(*) as count 
     FROM logs 
     GROUP BY type 
     ORDER BY count DESC`
  );

  // 转换 count 为数字类型
  const typeStats = typeStatsRaw.map(item => ({
    type: item.type,
    count: Number(item.count) || 0,
  }));

  // 按级别统计（所有日志）
  const levelStatsRaw = await query<{ level: string; count: string | number | bigint }>(
    `SELECT level, COUNT(*) as count 
     FROM logs 
     GROUP BY level 
     ORDER BY count DESC`
  );

  // 转换 count 为数字类型
  const levelStats = levelStatsRaw.map(item => ({
    level: item.level,
    count: Number(item.count) || 0,
  }));

  // 今天日志数
  const todayResult = await queryOne<{ count: string | number | bigint }>(
    'SELECT COUNT(*) as count FROM logs WHERE created_at >= ?',
    [todayStr]
  );
  const todayCount = todayResult ? Number(todayResult.count) || 0 : 0;

  success(ctx, {
    total,
    typeStats,
    levelStats,
    todayCount,
  });
}

/**
 * 筛选超频请求
 * 超频请求定义：在时间窗口内（60秒），同一个IP对同一个API请求次数超过阈值（60次）
 */
export async function getAbnormalRequests(ctx: Context): Promise<void> {
  const {
    page = 1,
    pageSize = 20,
    ip,
    userId,
    startTime,
    endTime,
    url,
    windowSeconds = 60,
    threshold = 60,
  } = ctx.request.body as {
    page?: number;
    pageSize?: number;
    ip?: string;
    userId?: string;
    startTime?: string;
    endTime?: string;
    url?: string;
    windowSeconds?: number; // 时间窗口（秒），默认60秒
    threshold?: number; // 阈值（次数），默认60次
  };

  // 限制每页最大数量
  const maxPageSize = 100;
  const limitPageSize = Math.min(pageSize, maxPageSize);

  // 构建基础查询条件
  let baseSql = 'SELECT * FROM logs WHERE type = ?';
  const baseParams: any[] = ['api'];

  // 添加额外筛选条件
  if (ip) {
    baseSql += ' AND ip = ?';
    baseParams.push(ip);
  }

  if (userId) {
    baseSql += ' AND user_id = ?';
    baseParams.push(userId);
  }

  if (startTime) {
    baseSql += ' AND created_at >= ?';
    baseParams.push(startTime);
  }

  if (endTime) {
    baseSql += ' AND created_at <= ?';
    baseParams.push(endTime);
  }

  if (url) {
    baseSql += ' AND url LIKE ?';
    baseParams.push(`%${url}%`);
  }

  // 查询所有符合条件的API日志
  const allLogs = await query<Log>(baseSql, baseParams);

  // 按IP和URL分组，统计每个组合在时间窗口内的请求次数
  const frequencyMap = new Map<string, {
    ip: string;
    url: string;
    count: number;
    firstRequest: Date;
    lastRequest: Date;
    logs: Log[];
  }>();

  for (const log of allLogs) {
    const key = `${log.ip}:${log.url}`;
    const logTime = new Date(log.created_at);
    
    if (!frequencyMap.has(key)) {
      frequencyMap.set(key, {
        ip: log.ip || 'unknown',
        url: log.url || 'unknown',
        count: 0,
        firstRequest: logTime,
        lastRequest: logTime,
        logs: [],
      });
    }

    const entry = frequencyMap.get(key)!;
    entry.logs.push(log);
    
    // 更新时间范围
    if (logTime < entry.firstRequest) {
      entry.firstRequest = logTime;
    }
    if (logTime > entry.lastRequest) {
      entry.lastRequest = logTime;
    }
  }

  // 分析每个IP+URL组合，找出超频请求
  const abnormalGroups: Array<{
    ip: string;
    url: string;
    count: number;
    windowStart: Date;
    windowEnd: Date;
    logs: Log[];
  }> = [];

  for (const entry of frequencyMap.values()) {
    // 按时间排序日志
    entry.logs.sort((a, b) => new Date(a.created_at).getTime() - new Date(b.created_at).getTime());

    // 滑动窗口检测超频
    for (let i = 0; i < entry.logs.length; i++) {
      const windowStart = new Date(entry.logs[i].created_at);
      const windowEnd = new Date(windowStart.getTime() + windowSeconds * 1000);
      
      // 统计窗口内的请求数
      const windowLogs = entry.logs.filter(log => {
        const logTime = new Date(log.created_at);
        return logTime >= windowStart && logTime <= windowEnd;
      });

      if (windowLogs.length > threshold) {
        // 找到超频请求组
        abnormalGroups.push({
          ip: entry.ip,
          url: entry.url,
          count: windowLogs.length,
          windowStart,
          windowEnd,
          logs: windowLogs,
        });
        // 找到第一个超频窗口后，跳出内层循环，避免重复统计
        break;
      }
    }
  }

  // 去重：同一个IP+URL组合只保留一个超频组
  const uniqueGroups = new Map<string, typeof abnormalGroups[0]>();
  for (const group of abnormalGroups) {
    const key = `${group.ip}:${group.url}`;
    if (!uniqueGroups.has(key) || group.count > uniqueGroups.get(key)!.count) {
      uniqueGroups.set(key, group);
    }
  }

  // 转换为列表并排序（按请求次数降序）
  const sortedGroups = Array.from(uniqueGroups.values()).sort((a, b) => b.count - a.count);

  // 分页处理
  const total = sortedGroups.length;
  const startIndex = (page - 1) * limitPageSize;
  const endIndex = startIndex + limitPageSize;
  const pagedGroups = sortedGroups.slice(startIndex, endIndex);

  // 格式化返回数据
  const abnormalList = pagedGroups.map(group => {
    // 获取该组中的第一条和最后一条日志
    const firstLog = group.logs[0];
    const lastLog = group.logs[group.logs.length - 1];
    
    // 提取用户ID（取第一条日志的用户ID）
    const userId = firstLog.user_id;

    return {
      ip: group.ip,
      url: group.url,
      count: group.count,
      threshold,
      windowSeconds,
      windowStart: group.windowStart,
      windowEnd: group.windowEnd,
      userId,
      firstRequestTime: firstLog.created_at,
      lastRequestTime: lastLog.created_at,
      // 返回部分日志详情（最多10条）
      sampleLogs: group.logs.slice(0, 10).map(log => ({
        id: log.id,
        requestId: log.request_id,
        userId: log.user_id,
        createdAt: log.created_at,
        message: log.message,
      })),
    };
  });

  success(ctx, {
    list: abnormalList,
    total,
    page,
    pageSize: limitPageSize,
  });
}

